'use client'

import type { FC } from 'react'
import { useEffect } from 'react'
import type { EditorState } from 'lexical'
import { $getRoot, TextNode } from 'lexical'
import { CodeNode } from '@lexical/code'
import { LexicalComposer } from '@lexical/react/LexicalComposer'
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
import { ContentEditable } from '@lexical/react/LexicalContentEditable'
import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary'
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin'
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'
// import TreeView from './plugins/tree-view'
import Placeholder from './plugins/placeholder'
import ComponentPickerBlock from './plugins/component-picker-block/index'
import { ContextBlock, ContextBlockNode, ContextBlockReplacementBlock } from './plugins/context-block/index'
import { QueryBlock, QueryBlockNode, QueryBlockReplacementBlock } from './plugins/query-block/index'
import { HistoryBlock, HistoryBlockNode, HistoryBlockReplacementBlock } from './plugins/history-block/index'
import {
  WorkflowVariableBlock,
  WorkflowVariableBlockNode,
  WorkflowVariableBlockReplacementBlock
} from './plugins/workflow-variable-block/index'
import VariableBlock from './plugins/variable-block/index'
import VariableValueBlock from './plugins/variable-value-block/index'
import { VariableValueBlockNode } from './plugins/variable-value-block/node'
import { CustomTextNode } from './plugins/custom-text/node'
import OnBlurBlock from './plugins/on-blur-or-focus-block'
import UpdateBlock from './plugins/update-block'
import { textToEditorState } from './utils'
import type {
  ContextBlockType,
  ExternalToolBlockType,
  HistoryBlockType,
  QueryBlockType,
  VariableBlockType,
  WorkflowVariableBlockType
} from './types'
import { UPDATE_DATASETS_EVENT_EMITTER, UPDATE_HISTORY_EVENT_EMITTER } from './constants'
import { useEventEmitterContextContext } from '@common/contexts/EventEmitterContext'

export type PromptEditorProps = {
  instanceId?: string
  compact?: boolean
  className?: string
  placeholder?: string
  placeholderClassName?: string
  style?: React.CSSProperties
  value?: string
  editable?: boolean
  onChange?: (text: string) => void
  onBlur?: () => void
  onFocus?: () => void
  contextBlock?: ContextBlockType
  queryBlock?: QueryBlockType
  historyBlock?: HistoryBlockType
  variableBlock?: VariableBlockType
  externalToolBlock?: ExternalToolBlockType
  workflowVariableBlock?: WorkflowVariableBlockType
}

const PromptEditor: FC<PromptEditorProps> = ({
  instanceId,
  compact,
  className,
  placeholder,
  placeholderClassName,
  style,
  value,
  editable = true,
  onChange,
  onBlur,
  onFocus,
  contextBlock,
  queryBlock,
  historyBlock,
  variableBlock,
  externalToolBlock,
  workflowVariableBlock
}) => {
  const { eventEmitter } = useEventEmitterContextContext()
  const initialConfig = {
    namespace: 'prompt-editor',
    nodes: [
      CodeNode,
      CustomTextNode,
      {
        replace: TextNode,
        with: (node: TextNode) => new CustomTextNode(node.__text)
      },
      ContextBlockNode,
      HistoryBlockNode,
      QueryBlockNode,
      WorkflowVariableBlockNode,
      VariableValueBlockNode
    ],
    editorState: textToEditorState(value || ''),
    onError: (error: Error) => {
      throw error
    }
  }

  const handleEditorChange = (editorState: EditorState) => {
    const text = editorState.read(() => {
      return $getRoot()
        .getChildren()
        .map((p) => p.getTextContent())
        .join('\n')
    })
    if (onChange) onChange(text)
  }

  useEffect(() => {
    eventEmitter?.emit({
      type: UPDATE_DATASETS_EVENT_EMITTER,
      payload: contextBlock?.datasets
    } as any)
  }, [eventEmitter, contextBlock?.datasets])
  useEffect(() => {
    eventEmitter?.emit({
      type: UPDATE_HISTORY_EVENT_EMITTER,
      payload: historyBlock?.history
    } as any)
  }, [eventEmitter, historyBlock?.history])

  return (
    <LexicalComposer initialConfig={{ ...initialConfig, editable }}>
      <div className="relative min-h-5">
        <RichTextPlugin
          contentEditable={
            <ContentEditable
              className={`${className} outline-none ${compact ? 'leading-5 text-[13px]' : 'leading-6 text-sm'} text-gray-700`}
              style={style || {}}
            />
          }
          placeholder={<Placeholder value={placeholder} className={placeholderClassName} compact={compact} />}
          ErrorBoundary={LexicalErrorBoundary}
        />
        <ComponentPickerBlock
          triggerString="/"
          contextBlock={contextBlock}
          historyBlock={historyBlock}
          queryBlock={queryBlock}
          variableBlock={variableBlock}
          externalToolBlock={externalToolBlock}
          workflowVariableBlock={workflowVariableBlock}
        />
        <ComponentPickerBlock
          triggerString="{"
          contextBlock={contextBlock}
          historyBlock={historyBlock}
          queryBlock={queryBlock}
          variableBlock={variableBlock}
          externalToolBlock={externalToolBlock}
          workflowVariableBlock={workflowVariableBlock}
        />
        {contextBlock?.show && (
          <>
            <ContextBlock {...contextBlock} />
            <ContextBlockReplacementBlock {...contextBlock} />
          </>
        )}
        {queryBlock?.show && (
          <>
            <QueryBlock {...queryBlock} />
            <QueryBlockReplacementBlock />
          </>
        )}
        {historyBlock?.show && (
          <>
            <HistoryBlock {...historyBlock} />
            <HistoryBlockReplacementBlock {...historyBlock} />
          </>
        )}
        {(variableBlock?.show || externalToolBlock?.show) && (
          <>
            <VariableBlock />
            <VariableValueBlock />
          </>
        )}
        {workflowVariableBlock?.show && (
          <>
            <WorkflowVariableBlock {...workflowVariableBlock} />
            <WorkflowVariableBlockReplacementBlock {...workflowVariableBlock} />
          </>
        )}
        <OnChangePlugin onChange={handleEditorChange} />
        <OnBlurBlock onBlur={onBlur} onFocus={onFocus} />
        <UpdateBlock instanceId={instanceId} />
        <HistoryPlugin />
        {/* <TreeView /> */}
      </div>
    </LexicalComposer>
  )
}

export default PromptEditor
